home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / ipServer / RCS / tcpSock.c,v < prev    next >
Encoding:
Text File  |  1991-11-13  |  44.1 KB  |  1,842 lines

  1. head     1.12;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.12
  10. date     91.11.12.20.56.31;  author mottsmth;  state Exp;
  11. branches ;
  12. next     1.11;
  13.  
  14. 1.11
  15. date     90.02.22.14.22.20;  author ouster;  state Exp;
  16. branches ;
  17. next     1.10;
  18.  
  19. 1.10
  20. date     89.05.19.15.24.24;  author douglis;  state Exp;
  21. branches ;
  22. next     1.9;
  23.  
  24. 1.9
  25. date     89.03.23.10.55.46;  author brent;  state Exp;
  26. branches ;
  27. next     1.8;
  28.  
  29. 1.8
  30. date     89.03.23.09.54.04;  author brent;  state Exp;
  31. branches ;
  32. next     1.7;
  33.  
  34. 1.7
  35. date     89.02.21.10.10.54;  author brent;  state Exp;
  36. branches ;
  37. next     1.6;
  38.  
  39. 1.6
  40. date     88.12.14.09.21.33;  author douglis;  state Exp;
  41. branches ;
  42. next     1.5;
  43.  
  44. 1.5
  45. date     88.10.24.13.09.57;  author douglis;  state Exp;
  46. branches ;
  47. next     1.4;
  48.  
  49. 1.4
  50. date     88.10.17.10.20.10;  author ouster;  state Exp;
  51. branches ;
  52. next     1.3;
  53.  
  54. 1.3
  55. date     88.08.16.11.19.27;  author mendel;  state Exp;
  56. branches ;
  57. next     1.2;
  58.  
  59. 1.2
  60. date     88.04.27.09.10.30;  author brent;  state Exp;
  61. branches ;
  62. next     1.1;
  63.  
  64. 1.1
  65. date     87.12.14.22.08.04;  author andrew;  state Exp;
  66. branches ;
  67. next     ;
  68.  
  69.  
  70. desc
  71. @@
  72.  
  73.  
  74. 1.12
  75. log
  76. @Make sure socket protocol is TCP before doing
  77. an option on it. (TCP_SocketSetOpt).
  78. @
  79. text
  80. @/* 
  81.  * tcpSock.c --
  82.  *
  83.  *    Protocol-dependent routines to implement the semantics of
  84.  *    the socket operations defined in sockOps.c. The routines in
  85.  *    this file handle TCP stream sockets.
  86.  *
  87.  *    Based on the following 4.3BSD files:
  88.  *    "@@(#)tcp_subr.c      7.13 (Berkeley) 12/7/87"
  89.  *    "@@(#)tcp_usrreq.c 7.8 (Berkeley) 3/16/88"
  90.  *
  91.  *     To do:
  92.  *    1) fix bug in socket closing: sockPtr is not deallocated.
  93.  *
  94.  *
  95.  * Copyright 1987 Regents of the University of California
  96.  * All rights reserved.
  97.  * Permission to use, copy, modify, and distribute this
  98.  * software and its documentation for any purpose and without
  99.  * fee is hereby granted, provided that the above copyright
  100.  * notice appear in all copies.  The University of California
  101.  * makes no representations about the suitability of this
  102.  * software for any purpose.  It is provided "as is" without
  103.  * express or implied warranty.
  104.  */
  105.  
  106. #ifndef lint
  107. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpSock.c,v 1.11 90/02/22 14:22:20 ouster Exp Locker: mottsmth $ SPRITE (Berkeley)";
  108. #endif not lint
  109.  
  110.  
  111. #include "sprite.h"
  112. #include "inet.h"
  113. #include "netInet.h"
  114. #include "ipServer.h"
  115. #include "stat.h"
  116. #include "socket.h"
  117. #include "sockInt.h"
  118. #include "tcp.h"
  119. #include "tcpInt.h"
  120. #include "route.h"
  121.  
  122. /*
  123.  * Default size (in bytes) of a socket's send and receive buffers.
  124.  */
  125. #define SEND_SPACE    TCP_BUF_SIZE
  126. #define RECV_SPACE    TCP_BUF_SIZE
  127.  
  128.  
  129. static unsigned int    GetPort();
  130. static Boolean        ConnQueueFull();
  131. static Boolean        ConnQueueNotEmpty();
  132. static void        ConnQueueAppend();
  133. static Sock_SharedInfo    *ConnQueueNext();
  134. TCPControlBlock *curTCB;
  135.  
  136.  
  137.  
  138. /*
  139.  *----------------------------------------------------------------------
  140.  *
  141.  * TCP_SocketOpen --
  142.  *
  143.  *    This routine completes the TCP-dependent initialization of the
  144.  *    socket. A TCP control block is allocated and initialized. 
  145.  *    The send and receive buffers are also initialized.
  146.  *
  147.  * Results:
  148.  *    SUCCESS        - always returned.
  149.  *
  150.  * Side effects:
  151.  *    Memory for the TCP control block is allocated.
  152.  *
  153.  *----------------------------------------------------------------------
  154.  */
  155.  
  156. /*ARGSUSED*/
  157. ReturnStatus
  158. TCP_SocketOpen(sockPtr, userID)
  159.     Sock_SharedInfo    *sockPtr;    /* Socket to be initialized. */
  160.     int            userID;        /* Client's user ID. Ignored. */
  161. {
  162.     register TCPControlBlock *tcbPtr;
  163.  
  164.     tcbPtr = (TCPControlBlock *) malloc(sizeof(TCPControlBlock));
  165.     sockPtr->protoData = (ClientData) tcbPtr;
  166.  
  167.     bzero( (Address) tcbPtr, sizeof(*tcbPtr));
  168.     tcbPtr->state        = CLOSED;
  169.     tcbPtr->maxSegSize        = TCP_MAX_SEG_SIZE;
  170.     tcbPtr->flags        = 0;
  171.     /*
  172.      * Initialize the smoothed RTT to 0 so we can tell that we have no
  173.      * RTT estimate.  Set rttvar so that smooth RTT + 2 * rttVar gives
  174.      * reasonable initial retransmit time.
  175.      */
  176.     tcbPtr->srtt        = TCP_SRTT_BASE_TIME;
  177.     tcbPtr->rttvar        = TCP_SRTT_DEFLT_TIME << 2;
  178.     TCP_TIMER_RANGESET(tcbPtr->rxtcur, 
  179.     ((TCP_SRTT_BASE_TIME >> 2) + (TCP_SRTT_DEFLT_TIME << 2)) >> 1,
  180.     TCP_MIN_REXMT_TIME, TCP_MAX_REXMT_TIME);
  181.     tcbPtr->send.congWindow    = SEND_SPACE;
  182.     tcbPtr->send.cwSizeThresh    = 65535    /* XXX */;
  183.     List_Init(&tcbPtr->reassList);
  184.  
  185.     Sock_BufAlloc(sockPtr, SOCK_RECV_BUF, RECV_SPACE);
  186.     Sock_BufAlloc(sockPtr, SOCK_SEND_BUF, SEND_SPACE);
  187.     return(SUCCESS);
  188. }
  189.  
  190.  
  191. /*
  192.  *----------------------------------------------------------------------
  193.  *
  194.  * TCP_SocketClose --
  195.  *
  196.  *    Remove data from the socket's read and write queues and
  197.  *    deallocate the TCP control block.
  198.  *
  199.  *  To do:
  200.  *      1) make sure can free read/write queues (tcp may need to wait
  201.  *         for acks before the data can be freed).
  202.  *      2) reject waiting connection attempts
  203.  *
  204.  * Results:
  205.  *    SUCCESS        - the operation was successful.
  206.  *    FS_WOULD_BLOCK    - the socket can't be closed yet because some data
  207.  *              in the send buffer has not been ACKed.
  208.  *
  209.  * Side effects:
  210.  *    The TCB may be destroyed. A packet may be sent to the remote host.
  211.  *
  212.  *----------------------------------------------------------------------
  213.  */
  214.  
  215. ReturnStatus
  216. TCP_SocketClose(sockPtr)
  217.     Sock_SharedInfo    *sockPtr;    /* Socket to be closed. */
  218. {
  219.     register TCPControlBlock *tcbPtr;
  220.     tcbPtr = (TCPControlBlock *) sockPtr->protoData;
  221.  
  222.     /*
  223.      * The TCB will be NULL if the connection gets reset before
  224.      * being fully established.
  225.      */
  226.     if (tcbPtr == (TCPControlBlock *) NULL) {
  227.     return(SUCCESS);
  228.     }
  229.  
  230.  
  231.     switch (tcbPtr->state) {
  232.     /*
  233.      * If accepting connections, go through the queue of waiting 
  234.      * connections and drop them.
  235.      */
  236.     case LISTEN:
  237.         while (ConnQueueNotEmpty(sockPtr, FALSE)) {
  238.         Sock_InfoPtr    connPtr = ConnQueueNext(sockPtr);
  239.  
  240.         TCPDropConnection(connPtr, 
  241.                 (TCPControlBlock *) connPtr->protoData, 
  242.                 (ReturnStatus)NET_CONNECTION_RESET);
  243.         }
  244.  
  245.         /* Fall into ... */
  246.  
  247.     case CLOSED:
  248.     case SYN_SENT:
  249.     case SYN_RECEIVED:
  250.         TCPCloseConnection(sockPtr, tcbPtr);
  251.         return(SUCCESS);
  252.         break;
  253.  
  254.  
  255.     default:
  256.         if ((sockPtr->options & NET_OPT_LINGER) && (sockPtr->linger == 0)) {
  257.         /*
  258.          * If linger wanted and not lingering then drop the connection.
  259.          */
  260.         TCPDropConnection(sockPtr, tcbPtr, 
  261.                     (ReturnStatus)NET_CONNECTION_RESET);
  262.         } else {
  263.         Sock_Disconnecting(sockPtr);
  264.         Sock_BufRemove(sockPtr, SOCK_RECV_BUF, -1);
  265.  
  266.         switch (tcbPtr->state) {
  267.             case ESTABLISHED:
  268.             tcbPtr->state = FIN_WAIT_1;
  269.             break;
  270.  
  271.             case CLOSE_WAIT:
  272.             tcbPtr->state = LAST_ACK;
  273.             break;
  274.  
  275.             case FIN_WAIT_2:
  276.             case TIME_WAIT:
  277.             Sock_Disconnected(sockPtr);
  278.             break;
  279.  
  280.             case FIN_WAIT_1:
  281.             case LAST_ACK:
  282.             break;
  283.         }
  284.         (void) TCPOutput(sockPtr, tcbPtr);
  285.         }
  286.         break;
  287.     }
  288.     /*
  289.      * Tell the client that it has to wait for the remote host to 
  290.      * acknowledge our close.
  291.      */
  292.     return(FS_WOULD_BLOCK);
  293. }
  294.  
  295.  
  296. /*
  297.  *----------------------------------------------------------------------
  298.  *
  299.  * TCP_SocketRead --
  300.  *
  301.  *    Return data to a client doing a read on a TCP socket.
  302.  *    Normal or urgent ("out-of-band") data can be retreived.
  303.  *
  304.  * Results:
  305.  *    SUCCESS        - the operation was successful.
  306.  *    FS_WOULD_BLOCK    - the read queue was empty or didn't have
  307.  *              enough data to fill the buffer.
  308.  *
  309.  * Side effects:
  310.  *    Data can be removed from the receive buffer.
  311.  *
  312.  *----------------------------------------------------------------------
  313.  */
  314.  
  315. ReturnStatus
  316. TCP_SocketRead(privPtr, bufSize, buffer, amountReadPtr)
  317.     register Sock_PrivInfo *privPtr;    /* Socket with data. */
  318.     int        bufSize;        /* Amount of data to read. */
  319.     Address    buffer;            /* Place to store the data. */
  320.     int        *amountReadPtr;        /* Actual amount placed in buffer. */
  321. {
  322.     ReturnStatus status;
  323.     Sock_SharedInfo    *sharePtr = privPtr->sharePtr;
  324.     TCPControlBlock    *tcbPtr   = (TCPControlBlock *)sharePtr->protoData;
  325.     int recvFlags = privPtr->recvFlags | SOCK_BUF_STREAM;
  326.     int amtRead = 0;
  327.  
  328.     if (sharePtr->state != CONNECTED) {
  329.     return(NET_NOT_CONNECTED);
  330.     }
  331.  
  332.     /*
  333.      * The user wants urgent ("out-of-band") data.
  334.      */
  335.     if (recvFlags & NET_OUT_OF_BAND) {
  336.     /*
  337.      * If there's no urgent data or urgent data is supposed to remain
  338.      * in-line with other data or the urgent data is not available
  339.      * any more, then return an error.
  340.      */
  341.     if (((tcbPtr->urgentBufPos == 0) &&
  342.           !(sharePtr->flags & SOCK_URGENT_DATA_NEXT)) ||
  343.         Sock_IsOptionSet(sharePtr, NET_OPT_OOB_INLINE) ||
  344.         tcbPtr->flags & TCP_HAD_URGENT_DATA) {
  345.  
  346.         status = GEN_INVALID_ARG;
  347.     } else if (!(tcbPtr->flags & TCP_HAVE_URGENT_DATA)) {
  348.         /*
  349.          * There's urgent data but it's not yet 
  350.          */
  351.         status = FS_WOULD_BLOCK;
  352.     } else {
  353.  
  354.         amtRead = 1;
  355.         *buffer = tcbPtr->urgentData;
  356.         if (!(recvFlags & NET_PEEK)) {
  357.         /*
  358.          * If this is a destructive read, then turn off the HAVE bit
  359.          * and turn on the HAD bit to indicate the urgent data's 
  360.          * been read.
  361.          */
  362.         tcbPtr->flags ^= (TCP_HAVE_URGENT_DATA | TCP_HAD_URGENT_DATA);
  363.         }
  364.         status = SUCCESS;
  365.     }
  366.     } else {
  367.  
  368.     /*
  369.      * Return "normal" data to the user. 
  370.      */
  371.  
  372.     sharePtr->flags &= ~SOCK_URGENT_DATA_NEXT;
  373.     if ((tcbPtr->urgentBufPos > 0) && (bufSize > tcbPtr->urgentBufPos)) {
  374.         /*
  375.          * There's urgent data in the buffer -- just read enough normal 
  376.          * data until the position of the urgent data is reached.
  377.          */
  378.         bufSize = tcbPtr->urgentBufPos;
  379.     }
  380.  
  381.     status = Sock_BufFetch(sharePtr, recvFlags, bufSize, buffer, &amtRead, 
  382.             (Net_InetSocketAddr *) NULL);
  383.  
  384.     if (!(recvFlags & NET_PEEK)) {
  385.         tcbPtr->urgentBufPos -= amtRead;
  386.         if (tcbPtr->urgentBufPos == 0) {
  387.         sharePtr->flags |= SOCK_URGENT_DATA_NEXT;
  388.         }
  389.  
  390.         if (status == SUCCESS) {
  391.         /*
  392.          * See if we need to send a window update to the peer.
  393.          */
  394.         (void) TCPOutput(sharePtr, tcbPtr);
  395.         }
  396.     }
  397.     }
  398.  
  399.     if (amountReadPtr != (int *) NULL) {
  400.     *amountReadPtr = amtRead;
  401.     }
  402.  
  403.     if (status != FS_WOULD_BLOCK) {
  404.     privPtr->recvFlags = 0;
  405.     }
  406.     return(status);
  407. }
  408.  
  409. /*
  410.  *----------------------------------------------------------------------
  411.  *
  412.  * TCP_SocketWrite --
  413.  *
  414.  *    This routine appends the data to be written to the socket's
  415.  *    send buffer and calls the output routine to send the data to
  416.  *    the remote host.
  417.  *
  418.  * Results:
  419.  *    SUCCESS        - the operation was successful.
  420.  *    FS_WOULD_BLOCK    - no room in the buffer to hold the data.
  421.  *
  422.  * Side effects:
  423.  *    Packets containing the data may be sent.
  424.  *
  425.  *----------------------------------------------------------------------
  426.  */
  427.  
  428. ReturnStatus
  429. TCP_SocketWrite(privPtr, packetPtr, amtWrittenPtr)
  430.     Sock_PrivInfo    *privPtr;    /* Socket to write to. */ 
  431.     IPS_Packet        *packetPtr;    /* Packet descriptor containing 
  432.                      * data to be written. */
  433.     int            *amtWrittenPtr;    /* Actual amount of data written. */
  434. {
  435.     ReturnStatus status;
  436.     Sock_SharedInfo    *sharePtr = privPtr->sharePtr;
  437.  
  438.     if (sharePtr->state != CONNECTED) {
  439.     return(NET_NOT_CONNECTED);
  440.     }
  441.  
  442.     if ((privPtr->sendInfoValid) && 
  443.     (privPtr->sendInfo.flags & NET_OUT_OF_BAND)) {
  444.  
  445.     TCPControlBlock    *tcbPtr   = (TCPControlBlock *)sharePtr->protoData;
  446.  
  447.     status = Sock_BufAppend(sharePtr, SOCK_SEND_BUF, FALSE,
  448.         packetPtr->dataLen, packetPtr->data, packetPtr->base, 
  449.         (Net_InetSocketAddr *) NULL, amtWrittenPtr);
  450.  
  451.     /*
  452.      * According to RFC1011 "Assigned Internet Protocols" (May 1987), 
  453.      * the urgent pointer points to the last octet of urgent data.  
  454.      * We continue, however, to consider it to indicate the first octet 
  455.      * of data past the urgent section.  Otherwise, send.urgentPtr 
  456.      * should be one lower. (This is the same behavior as 4.3BSD).
  457.      */
  458.     if (status == SUCCESS) {
  459.         tcbPtr->send.urgentPtr = tcbPtr->send.unAck + 
  460.             Sock_BufSize(sharePtr, SOCK_SEND_BUF, SOCK_BUF_USED);
  461.         tcbPtr->force = TRUE;
  462.         (void) TCPOutput(sharePtr, tcbPtr);
  463.         tcbPtr->force = FALSE;
  464.     } else if (*amtWrittenPtr != 0) {
  465.         TCPOutput(sharePtr, tcbPtr);
  466.     }
  467.     } else {
  468.     status = Sock_BufAppend(sharePtr, SOCK_SEND_BUF, FALSE,
  469.         packetPtr->dataLen, packetPtr->data, packetPtr->base, 
  470.         (Net_InetSocketAddr *) NULL, amtWrittenPtr);
  471.     if (*amtWrittenPtr != 0) {
  472.         (void) TCPOutput(sharePtr, (TCPControlBlock *)sharePtr->protoData);
  473.     }
  474.     }
  475.  
  476.     if (status == SUCCESS) {
  477.     privPtr->sendInfoValid = FALSE;
  478.     }
  479.     return(status);
  480. }
  481.  
  482.  
  483. /*
  484.  *----------------------------------------------------------------------
  485.  *
  486.  * TCP_SocketSelect --
  487.  *
  488.  *    This routine checks the socket to see if there is
  489.  *    1) data in the receive buffer to be read (active sockets),
  490.  *    2) a new connection waiting (passive sockets),
  491.  *    3) space in the send buffer for new data.
  492.  *    4) urgent data to be read.
  493.  *
  494.  * Results:
  495.  *    An or'd combination of FS_READBLE, FS_WRITABLE, FS_EXCEPTION.
  496.  *
  497.  * Side effects:
  498.  *    None.
  499.  *
  500.  *----------------------------------------------------------------------
  501.  */
  502.  
  503. int
  504. TCP_SocketSelect(sockPtr)
  505.     register Sock_SharedInfo    *sockPtr;    /* Socket to be selected. */
  506. {
  507.     int flags = 0;
  508.     TCPControlBlock    *tcbPtr = (TCPControlBlock *)sockPtr->protoData;
  509.  
  510.     if (sockPtr->state == LISTENING) {
  511.     if (ConnQueueNotEmpty(sockPtr, TRUE)) {
  512.         flags |= FS_READABLE;
  513.     }
  514.     } else if (Sock_IsRecvStopped(sockPtr) || 
  515.           ((sockPtr->state == CONNECTED) &&
  516.           (Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_USED) > 0))) {
  517.     flags |= FS_READABLE;
  518.     }
  519.  
  520.     if (Sock_IsSendStopped(sockPtr) || 
  521.        ((sockPtr->state == CONNECTED) &&
  522.        (Sock_BufSize(sockPtr, SOCK_SEND_BUF, SOCK_BUF_FREE) > 0))) {
  523.     flags |= FS_WRITABLE;
  524.     }
  525.  
  526.     /*
  527.      * If the socket has been connecting to a remote peer and the
  528.      * connection has just become established, then say the socket is
  529.      * writable (the client waits for establishment by selecting for the 
  530.      * for writing). 
  531.      *
  532.      * This flag is good for 1 select call: it has to be reset so the socket
  533.      * won't be writable forerver.
  534.      */
  535.     if (sockPtr->justEstablished) {
  536.     flags |= FS_WRITABLE;
  537.     sockPtr->justEstablished = FALSE;
  538.     }
  539.  
  540.     if ((sockPtr->state == CONNECTED) &&
  541.     ((sockPtr->flags & SOCK_URGENT_DATA_NEXT) ||
  542.     (tcbPtr->urgentBufPos > 0))) {
  543.     flags |= FS_EXCEPTION;
  544.     }
  545.     return(flags);
  546. }
  547.  
  548.  
  549. /*
  550.  *----------------------------------------------------------------------
  551.  *
  552.  * TCP_SocketBind --
  553.  *
  554.  *    Does TCP-specific stuff for assigning the local address of a socket.
  555.  *
  556.  * Results:
  557.  *    SUCCESS            - the operation was successful.
  558.  *    NET_ADDRESS_NOT_AVAIL    - an invalid address was given.
  559.  *    GEN_NO_PERMISSION    - the user tried to use a privileged port
  560.  *                  and did not have super-user privilege.
  561.  *    NET_ADDRESS_IN_USE    - the local <address,port> is already in use.
  562.  *
  563.  * Side effects:
  564.  *    The socket's state changes and the local address is changed.
  565.  *
  566.  *----------------------------------------------------------------------
  567.  */
  568.  
  569. ReturnStatus
  570. TCP_SocketBind(sockPtr, addrPtr, userID)
  571.     register Sock_SharedInfo    *sockPtr;/* Socket to be bound. */
  572.     Net_InetSocketAddr        *addrPtr;/* The local address for the socket. */
  573.     int                userID;    /* User ID of the process. */
  574. {
  575.     Net_InetSocketAddr    temp;
  576.     temp = *addrPtr;
  577.  
  578.     /*
  579.      * If a specific Inetnet address is given, make sure it is valid for
  580.      * this host (i.e. it is one of the addresses assigned to the host).
  581.      */
  582.  
  583.     if (temp.address != Net_HostToNetInt(NET_INET_ANY_ADDR)) {
  584.     if (!Rte_ValidateAddress(temp.address)) {
  585.         if (ips_Debug) {
  586.         (void) fprintf(stderr, "TCP_SocketBind: address not valid\n");
  587.         }
  588.         return(NET_ADDRESS_NOT_AVAIL);
  589.     }
  590.     }
  591.  
  592.     if (temp.port == 0) {
  593.     temp.port = GetPort(temp.address);
  594.     } else {
  595.     Boolean wildcard;
  596.  
  597.     /*
  598.      * Make sure the given port is OK to use. If the port # is in
  599.      * the reserved range then make sure the user has super-user
  600.      * privileges. 
  601.      */
  602.  
  603.     if ((Net_NetToHostShort(temp.port) < INET_PRIV_PORTS) && 
  604.         (userID != PROC_SUPER_USER_ID)) {
  605.         if (ips_Debug) {
  606.         (void) fprintf(stderr,
  607.                    "TCP_SocketBind: no permission for port %d, user %d\n",
  608.                    temp.port, userID);
  609.         }
  610.         return(GEN_NO_PERMISSION);
  611.     }
  612.  
  613.     /*
  614.      * Check for the uniqueness of the new local <address,port> tuple
  615.      * among all TCP sockets.  The REUSE_ADDR option specifies the
  616.      * strictness of the check.  If the option is not set, then the
  617.      * local tuple can't be used by us if any other TCP socket is
  618.      * using it.  A looser check is made if the option is set:  we can
  619.      * use the local tuple even if it is used by other sockets but
  620.      * only if their remote tuple is not the <NET_INET_ANY_ADDR,0>
  621.      * wildcard.
  622.      */
  623.  
  624.     if (Sock_IsOptionSet(sockPtr, NET_OPT_REUSE_ADDR)) {
  625.         wildcard = FALSE;
  626.     } else {
  627.         wildcard = TRUE;
  628.     }
  629.  
  630.     if (Sock_Match(TCP_PROTO_INDEX, temp.address, temp.port,
  631.             Net_HostToNetInt(NET_INET_ANY_ADDR), 0, wildcard) != 
  632.                     (Sock_InfoPtr    ) NULL) {
  633.         if (ips_Debug) {
  634.         (void) fprintf(stderr, "TCP_SocketBind: address in use\n");
  635.         }
  636.         return(NET_ADDRESS_IN_USE);
  637.     }
  638.     }
  639.  
  640.     sockPtr->local = temp;
  641.     sockPtr->state = HAVE_LOCAL_ADDR;
  642.     return(SUCCESS);
  643. }
  644.  
  645.  
  646. /*
  647.  *----------------------------------------------------------------------
  648.  *
  649.  * TCP_SocketConnect --
  650.  *
  651.  *    Establishes a connection with a remote host.
  652.  *
  653.  * Results:
  654.  *    SUCCESS            - the operation was successful.
  655.  *    NET_ALREADY_CONNECTED    - the socket is already connected to a remote
  656.  *                  host.
  657.  *    NET_ADDRESS_NOT_AVAIL    - an invalid remote port was used.
  658.  *    NET_ADDRESS_IN_USE    - the remote <address, port> is already used
  659.  *                  by another socket.
  660.  *    FS_WOULD_BLOCK        - a packet has been sent to the remote
  661.  *                  host but the user must wait until the host
  662.  *                  accepts the connection.
  663.  *    
  664.  * Side effects:
  665.  *    A packet is sent to the remote host to initiate the connection
  666.  *    handshake.
  667.  *
  668.  *----------------------------------------------------------------------
  669.  */
  670.  
  671. ReturnStatus
  672. TCP_SocketConnect(sockPtr, remoteAddrPtr, initialize)
  673.     register Sock_SharedInfo    *sockPtr;    /* Initialized socket. */
  674.     Net_InetSocketAddr        *remoteAddrPtr;    /* Remote <address,port> to 
  675.                           * connect to. */
  676.     Boolean            initialize;    /* If TRUE, initialize the TCB*/
  677. {
  678.     TCPControlBlock    *tcbPtr;
  679.     Net_InetSocketAddr    remote;
  680.  
  681.     remote = *remoteAddrPtr;
  682.     /*
  683.      * The socket's can only connect once so if it's in the process of 
  684.      * connecting or is already connected, return an error.
  685.      */
  686.  
  687.     if ((sockPtr->state == CONNECTING) || (sockPtr->state == CONNECTED))  {
  688.     return(NET_ALREADY_CONNECTED);
  689.     }
  690.  
  691.  
  692.     /*
  693.      * A valid remote port must be specified.
  694.      */
  695.     if (remote.port == 0) {
  696.     return(NET_ADDRESS_NOT_AVAIL);
  697.     }
  698.  
  699.     /*
  700.      * If the wildcard address or the broadcast wildcard are given, then
  701.      * use the official address (explicit or broadcast) for the server.
  702.      */
  703.  
  704.     if (remote.address == Net_HostToNetInt(NET_INET_ANY_ADDR)) {
  705.     remote.address = Rte_GetOfficialAddr(FALSE);
  706.     } else if (remote.address == Net_HostToNetInt(NET_INET_BROADCAST_ADDR)) {
  707.     remote.address = Rte_GetOfficialAddr(TRUE);
  708.     }
  709.  
  710.     if (sockPtr->local.address == Net_HostToNetInt(NET_INET_ANY_ADDR)) {
  711.     Net_InetAddress    localAddr;
  712.  
  713.     /*
  714.      * The socket doesn't have a local address part yet so 
  715.      * use the official address for this server. Make sure the
  716.      * <local <address,port> and remote <address,port>> tuple is
  717.      * unique among all open TCP sockets.
  718.      */
  719.  
  720.     localAddr = Rte_GetOfficialAddr(FALSE);
  721.     if (Sock_Match(TCP_PROTO_INDEX, localAddr, 
  722.         sockPtr->local.port, remote.address, remote.port, FALSE) !=
  723.         (Sock_InfoPtr    ) NULL) {
  724.         return(NET_ADDRESS_IN_USE);
  725.     }
  726.  
  727.     /*
  728.      * The socket has a unique address tuple. 
  729.      * If a local port has not been chosen yet, assign an unused value.
  730.      */
  731.  
  732.     sockPtr->local.address = localAddr;
  733.     if (sockPtr->local.port == 0) {
  734.         sockPtr->local.port = GetPort(localAddr);
  735.     }
  736.     } else {
  737.     /*
  738.      * The socket has a valid local <address, port>. Make sure the
  739.      * the <local, remote> tuple is unique among all open TCP sockets.
  740.      */
  741.  
  742.     if (Sock_Match(TCP_PROTO_INDEX, sockPtr->local.address, 
  743.         sockPtr->local.port, remote.address, remote.port, FALSE) !=
  744.         (Sock_InfoPtr    ) NULL) {
  745.         return(NET_ADDRESS_IN_USE);
  746.     }
  747.     }
  748.     sockPtr->remote    = remote;
  749.     sockPtr->state    = CONNECTING;
  750.  
  751.     if (!initialize) {
  752.     /*
  753.      * The caller will handle the initialization.
  754.      */
  755.     return(SUCCESS);
  756.     } 
  757.  
  758.     stats.tcp.connAttempts++;
  759.     tcbPtr = (TCPControlBlock *) sockPtr->protoData;
  760.     TCPMakeTemplateHdr(sockPtr, tcbPtr);
  761.     tcbPtr->state = SYN_SENT;
  762.     tcbPtr->timer[TCP_TIMER_KEEP_ALIVE] = TCP_KEEP_TIME_INIT;
  763.     tcbPtr->send.initial = tcpISS;
  764.     tcpISS += TCP_INIT_SEND_SEQ_INCR/2;
  765.     TCP_SEND_SEQ_INIT(tcbPtr);
  766.     (void) TCPOutput(sockPtr, tcbPtr);
  767.  
  768.     /*
  769.      * Tell the client to wait until out request is accepted.
  770.      * The client should call Fs_Select waiting for the socket
  771.      * to become writable.
  772.      */
  773.     return(FS_WOULD_BLOCK);
  774. }
  775.  
  776. /*
  777.  *----------------------------------------------------------------------
  778.  *
  779.  * TCP_SocketListen --
  780.  *
  781.  *    Make the the TCP socket into a passive socket by changing to the 
  782.  *    LISTENING state. In passive mode, the socket can wait for connection
  783.  *    requests from remote hosts. The backlog argument specifies how
  784.  *    many requests can be queued and not be immediately refused.
  785.  *
  786.  * Results:
  787.  *    SUCCESS            - the operation was successful.
  788.  *    NET_BAD_OPERATION    - The socket was in the wrong state.
  789.  *
  790.  * Side effects:
  791.  *    The socket state is changed to LISTEN, a connect info struct
  792.  *    is allocated and initialized.
  793.  *
  794.  *----------------------------------------------------------------------
  795.  */
  796.  
  797. ReturnStatus
  798. TCP_SocketListen(sockPtr, backlog, userID)
  799.     Sock_SharedInfo    *sockPtr;
  800.     int            backlog;    /* How many pending requests to 
  801.                       * queue before rejecting them. */
  802.     int            userID;        /* User ID of the process. */
  803. {
  804.     TCPControlBlock        *tcbPtr;
  805.     register TCPConnectInfo    *connectPtr; 
  806.  
  807.     /*
  808.      * The socket must have been just created or had a local address given to
  809.      * in order to go into listen mode. This means the socket can't be
  810.      * connected.
  811.      */
  812.  
  813.     if (sockPtr->state == CREATED) {
  814.     ReturnStatus        status;
  815.     Net_InetSocketAddr    sockAddr;
  816.  
  817.     /*
  818.      * Have to give the socket a local address.
  819.      */
  820.     sockAddr.address = Net_HostToNetInt(NET_INET_ANY_ADDR);
  821.     sockAddr.port = 0;
  822.     status = TCP_SocketBind(sockPtr, &sockAddr, userID);
  823.     if (status != SUCCESS) {
  824.         return(status);
  825.     }
  826.     } else if (sockPtr->state != HAVE_LOCAL_ADDR) {
  827.     return(NET_BAD_OPERATION);
  828.     }
  829.  
  830.     /*
  831.      * Make sure the backlog value is in the proper range.
  832.      */
  833.     if (backlog <= 0) {
  834.     backlog = 1;
  835.     } else if (backlog > TCP_MAX_NUM_CONNECTS) {
  836.     backlog = TCP_MAX_NUM_CONNECTS;
  837.     }
  838.  
  839.     connectPtr = (TCPConnectInfo *) malloc(sizeof(TCPConnectInfo));
  840.     connectPtr->head = 0;
  841.     connectPtr->tail = 0;
  842.     /*
  843.      * The queue is circular so it requires 1 slot to be unused in order
  844.      * to tell if the queue is full.
  845.      */
  846.     connectPtr->maxQueueSize = backlog + 1;
  847.  
  848.     tcbPtr = (TCPControlBlock *) sockPtr->protoData;
  849.     tcbPtr->connectPtr    = connectPtr;
  850.     tcbPtr->state    = LISTEN;
  851.     sockPtr->state    = LISTENING;
  852.     return(SUCCESS);
  853. }
  854.  
  855.  
  856. /*
  857.  *----------------------------------------------------------------------
  858.  *
  859.  * TCP_SocketAccept --
  860.  *
  861.  *    This routine handles the first part of accepting a waiting connection 
  862.  *    request. If there's a waiting request, a token is returned in 
  863.  *    outBuffer. This token must be used with the NET_IOC_ACCEPT_CONN_2
  864.  *    ioctl to complete the connection.
  865.  *
  866.  * Results:
  867.  *    SUCCESS            - a connect token was returned in outBuffer.
  868.  *    NET_BAD_OPERATION    - the socket is in the listening state.
  869.  *    NET_NO_CONNECTS        - no pending connect requests.
  870.  *
  871.  * Side effects:
  872.  *    None.
  873.  *
  874.  *----------------------------------------------------------------------
  875.  */
  876.  
  877. ReturnStatus
  878. TCP_SocketAccept(sockPtr, outBuffer)
  879.     register Sock_SharedInfo    *sockPtr;    /* Listening socket. */
  880.     Address            outBuffer;    /* Place to hold connect token*/
  881. {
  882.     if (sockPtr->state != LISTENING) {
  883.     return(NET_BAD_OPERATION);
  884.     }
  885.  
  886.     if (!ConnQueueNotEmpty(sockPtr, TRUE)) {
  887.     return(NET_NO_CONNECTS);
  888.     }
  889.  
  890.     *(ClientData *) outBuffer = (ClientData) ConnQueueNext(sockPtr);
  891.     return(SUCCESS);
  892. }
  893.  
  894.  
  895. /*
  896.  *----------------------------------------------------------------------
  897.  *
  898.  * TCP_SocketDestroy --
  899.  *
  900.  *    Destroys all TCP-related memory allocated to a socket.
  901.  *
  902.  * Results:
  903.  *    None.
  904.  *
  905.  * Side effects:
  906.  *    TCB memory is deallocated.
  907.  *
  908.  *----------------------------------------------------------------------
  909.  */
  910.  
  911. void
  912. TCP_SocketDestroy(data)
  913.     ClientData    data;        /* Really a ptr to the TCB. */
  914. {
  915.     TCPControlBlock *tcbPtr;
  916.     tcbPtr = (TCPControlBlock *) data;
  917.  
  918.     /*
  919.      * The TCB apparently may be NULL if the process owning the socket
  920.      * was killed asynchronously, so check against this so we don't
  921.      * deference a NULL pointer.
  922.      */
  923.     if (tcbPtr == (TCPControlBlock *) NULL) {
  924.     (void) fprintf(stderr, "TCP_SocketDestroy: tcb == NULL\n");
  925.     return;
  926.     }
  927.  
  928.     if (tcbPtr->connectPtr != (TCPConnectInfo *)NULL) {
  929.     free((char *) tcbPtr->connectPtr);
  930.     }
  931.     if (tcbPtr->templatePtr != (Net_TCPHeader *)NULL) {
  932.     free((char *) tcbPtr->templatePtr);
  933.     }
  934.     if (tcbPtr->IPTemplatePtr != (Net_IPHeader *)NULL) {
  935.     free((char *) tcbPtr->IPTemplatePtr);
  936.     }
  937.     TCPCleanReassList(tcbPtr);
  938.     TCPCancelTimers(tcbPtr);
  939.  
  940.     free((char *) tcbPtr);
  941. }
  942.  
  943.  
  944. /*
  945.  *----------------------------------------------------------------------
  946.  *
  947.  * TCP_SocketShutdown --
  948.  *
  949.  *    This routine gracefully closes down a TCP connection.
  950.  *
  951.  * Results:
  952.  *    SUCCESS        - the operation was successful.
  953.  *    ?         - result from TCPOutput.
  954.  *
  955.  * Side effects:
  956.  *    None.
  957.  *
  958.  *----------------------------------------------------------------------
  959.  */
  960.  
  961. ReturnStatus
  962. TCP_SocketShutdown(sockPtr, how)
  963.     Sock_SharedInfo    *sockPtr;
  964.     int            how;       /* What operations to shut down. */
  965. {
  966.     register TCPControlBlock *tcbPtr;
  967.     tcbPtr = (TCPControlBlock *) sockPtr->protoData;
  968.  
  969.     Sock_StopSending(sockPtr);
  970.  
  971.     switch (how) {
  972.     case 0:
  973.         Sock_StopRecv(sockPtr);
  974.         break;
  975.  
  976.     case 1:
  977.         Sock_StopSending(sockPtr);
  978.         break;
  979.  
  980.     case 2:
  981.         Sock_StopRecv(sockPtr);
  982.         Sock_StopSending(sockPtr);
  983.         break;
  984.     }
  985.  
  986.     if (tcbPtr != (TCPControlBlock *) NULL) {
  987.     switch (tcbPtr->state) {
  988.         case CLOSED:
  989.         case LISTEN:
  990.         case SYN_SENT:
  991.         TCPCloseConnection(sockPtr, tcbPtr);
  992.         tcbPtr = (TCPControlBlock *) NULL;
  993.         break;
  994.  
  995.         case SYN_RECEIVED:
  996.         case ESTABLISHED:
  997.         tcbPtr->state = FIN_WAIT_1;
  998.         break;
  999.  
  1000.         case CLOSE_WAIT:
  1001.         tcbPtr->state = LAST_ACK;
  1002.         break;
  1003.  
  1004.         case FIN_WAIT_2:
  1005.         case TIME_WAIT:
  1006.         Sock_Disconnected(sockPtr);
  1007.         break;
  1008.  
  1009.         case FIN_WAIT_1:
  1010.         case LAST_ACK:
  1011.         break;
  1012.     }
  1013.     if (tcbPtr != (TCPControlBlock *) NULL) {
  1014.         return(TCPOutput(sockPtr, tcbPtr));
  1015.     }
  1016.     }
  1017.     return(SUCCESS);
  1018. }
  1019.  
  1020.  
  1021. /*
  1022.  *----------------------------------------------------------------------
  1023.  *
  1024.  * TCP_SocketSetOpt --
  1025.  *
  1026.  *    This routine changes the value of a TCP socket option.
  1027.  *
  1028.  * Results:
  1029.  *    SUCCESS        - the operation was successful.
  1030.  *    GEN_INVALID_ARG - bad option or invalid buffer size.
  1031.  *
  1032.  * Side effects:
  1033.  *    The tcb flags are updated.
  1034.  *
  1035.  *----------------------------------------------------------------------
  1036.  */
  1037.  
  1038. ReturnStatus
  1039. TCP_SocketSetOpt(sockPtr, optName, inBufSize, inBuffer)
  1040.     Sock_SharedInfo    *sockPtr;
  1041.     int        optName;        /* Option. */
  1042.     int        inBufSize;        /* Size in bytes of inBuffer. */
  1043.     Address    inBuffer;        /* Buffer containing input data. */
  1044. {
  1045.     TCPControlBlock *tcbPtr;
  1046.  
  1047.     /*
  1048.      * We expect at least 4 bytes of data
  1049.      * and this better be a TCP protocol socket,
  1050.      * or it probably won't have a valid protoData field.
  1051.      */
  1052.     if ((inBufSize < sizeof(int)) ||
  1053.     (sockPtr->protoIndex != TCP_PROTO_INDEX )) {
  1054.     return(GEN_INVALID_ARG);
  1055.     }
  1056.  
  1057.     tcbPtr = (TCPControlBlock *) sockPtr->protoData;
  1058.  
  1059.     switch (optName) {
  1060.     case NET_OPT_TCP_NO_DELAY:
  1061.         if (*(int *)inBuffer) {
  1062.         tcbPtr->flags |= TCP_NO_DELAY;
  1063.         } else {
  1064.         tcbPtr->flags &= ~TCP_NO_DELAY;
  1065.         }
  1066.         break;
  1067.  
  1068.     case NET_OPT_TCP_MAX_SEG_SIZE:
  1069.         return(GEN_INVALID_ARG);    /* not implemented yet. */
  1070.         break;
  1071.  
  1072.     default:
  1073.         return(GEN_INVALID_ARG);
  1074.     }
  1075.     return(SUCCESS);
  1076. }
  1077.  
  1078.  
  1079. /*
  1080.  *----------------------------------------------------------------------
  1081.  *
  1082.  * TCP_SocketGetOpt --
  1083.  *
  1084.  *    This routine retreives the value of a TCP socket option.
  1085.  *
  1086.  * Results:
  1087.  *    SUCCESS        - the operation was successful.
  1088.  *    GEN_INVALID_ARG    - outbuffer too small or invalid option.
  1089.  *
  1090.  * Side effects:
  1091.  *    None.
  1092.  *
  1093.  *----------------------------------------------------------------------
  1094.  */
  1095.  
  1096. ReturnStatus
  1097. TCP_SocketGetOpt(sockPtr, optName, outBufSize, outBuffer)
  1098.     Sock_SharedInfo    *sockPtr;
  1099.     int        optName;        /* Option. */
  1100.     int        outBufSize;        /* Size in bytes of outBuffer. */
  1101.     Address    outBuffer;        /* Buffer to store output data. */
  1102. {
  1103.     TCPControlBlock *tcbPtr;
  1104.     tcbPtr = (TCPControlBlock *) sockPtr->protoData;
  1105.  
  1106.     /*
  1107.      * We want to return at least  4 bytes of data.
  1108.      */
  1109.     if (outBufSize < sizeof(int)) {
  1110.     return(GEN_INVALID_ARG);
  1111.     }
  1112.  
  1113.     switch (optName) {
  1114.     case NET_OPT_TCP_NO_DELAY:
  1115.         *(int *)outBuffer = tcbPtr->flags & TCP_NO_DELAY;
  1116.         break;
  1117.  
  1118.     case NET_OPT_TCP_MAX_SEG_SIZE:
  1119.         *(int *)outBuffer = tcbPtr->maxSegSize;
  1120.         break;
  1121.  
  1122.     default:
  1123.         return(GEN_INVALID_ARG);
  1124.     }
  1125.     return(SUCCESS);
  1126. }
  1127.  
  1128.  
  1129. /*
  1130.  *----------------------------------------------------------------------
  1131.  *
  1132.  * GetPort --
  1133.  *
  1134.  *    Given a local address, this routine finds a unused port and makes 
  1135.  *    sure it doesn't doesn't conflict with an existing socket's 
  1136.  *    binding address.
  1137.  *
  1138.  * Results:
  1139.  *    A new port #.
  1140.  *
  1141.  * Side effects:
  1142.  *    The port value is incremented.
  1143.  *
  1144.  *----------------------------------------------------------------------
  1145.  */
  1146.  
  1147. static unsigned int
  1148. GetPort(localAddr)
  1149.     Net_InetAddress    localAddr;
  1150. {
  1151.     static unsigned int port = INET_PRIV_PORTS;
  1152.     unsigned    int        netPort;
  1153.     unsigned    int        anyAddr = Net_HostToNetInt(NET_INET_ANY_ADDR);
  1154.  
  1155.     do {
  1156.     port++;
  1157.     if ((port < INET_PRIV_PORTS) || (port > INET_SERVER_PORTS)) {
  1158.         port = INET_PRIV_PORTS;
  1159.     }
  1160.     netPort = Net_HostToNetShort(port);
  1161.     } while (Sock_Match(TCP_PROTO_INDEX, localAddr, netPort, anyAddr, 0, 
  1162.             FALSE) != (Sock_InfoPtr    ) NULL);
  1163.     return(netPort);
  1164. }
  1165.  
  1166.  
  1167. /*
  1168.  *----------------------------------------------------------------------
  1169.  *
  1170.  * TCPCloneConnection --
  1171.  *
  1172.  *    Creates a new socket for a connected TCP socket in the 
  1173.  *    listening state.
  1174.  *
  1175.  * Results:
  1176.  *    A pointer to the Sock_SharedInfo struct for the new socket or
  1177.  *    NULL, if there was a problem.
  1178.  *
  1179.  * Side effects:
  1180.  *    A new TCP socket was created.
  1181.  *
  1182.  *----------------------------------------------------------------------
  1183.  */
  1184.  
  1185. Sock_InfoPtr    
  1186. TCPCloneConnection(sockPtr, localAddr, localPort, remoteAddr, remotePort)
  1187.     Sock_SharedInfo    *sockPtr;    /* Socket to be cloned. */
  1188.     Net_InetAddress    localAddr;    /* The new socket's local address,port*/
  1189.     unsigned int    localPort;
  1190.     Net_InetAddress    remoteAddr;    /* The remote host's address, port. */
  1191.     unsigned int    remotePort;
  1192. {
  1193.     Sock_SharedInfo    *newSockPtr;
  1194.     Net_InetSocketAddr    sockAddr;
  1195.  
  1196.     if (sockPtr->state != LISTENING) {
  1197.     panic(
  1198.         "TCPCloneConnection: old socket not listening %d\n",
  1199.         sockPtr->state);
  1200.     }
  1201.  
  1202.     /*
  1203.      * See if there's space to accept the connection.
  1204.      */
  1205.     if (ConnQueueFull(sockPtr)) {
  1206.     return((Sock_InfoPtr    )NULL);
  1207.     }
  1208.  
  1209.     newSockPtr = Sock_Clone(sockPtr, TRUE);
  1210.     /*
  1211.      * We don't know the user ID of the client, so just lie and
  1212.      * say it's the super-user. This is not a security hole because
  1213.      * the true permissions check was made when the socket was bound.
  1214.      */
  1215.     (void) TCP_SocketOpen(newSockPtr, PROC_SUPER_USER_ID);
  1216.  
  1217.     /*
  1218.      * Connect the socket to the remote peer. If the connect routine
  1219.      * discovers a problem, then destroy the new socket.
  1220.      */
  1221.  
  1222.     newSockPtr->local.address = localAddr;
  1223.     newSockPtr->local.port = localPort;
  1224.     newSockPtr->state = HAVE_LOCAL_ADDR;
  1225.  
  1226.     sockAddr.address = remoteAddr;
  1227.     sockAddr.port = remotePort;
  1228.     if (TCP_SocketConnect(newSockPtr, &sockAddr, FALSE) != SUCCESS) {
  1229.     Sock_Destroy(newSockPtr);
  1230.     return((Sock_InfoPtr    )NULL);
  1231.     }
  1232.  
  1233.     ConnQueueAppend(sockPtr, newSockPtr);
  1234.  
  1235.     return(newSockPtr);
  1236. }
  1237.  
  1238.  
  1239.  
  1240. /*
  1241.  *----------------------------------------------------------------------
  1242.  *
  1243.  * TCPSockToTCB --
  1244.  *
  1245.  *    Returns the pointer to the TCP control block for a TCP socket.
  1246.  *
  1247.  * Results:
  1248.  *    The tcb pointer.
  1249.  *
  1250.  * Side effects:
  1251.  *    None.
  1252.  *
  1253.  *----------------------------------------------------------------------
  1254.  */
  1255.  
  1256. TCPControlBlock *
  1257. TCPSockToTCB(sockPtr)
  1258.     Sock_InfoPtr    sockPtr;
  1259. {
  1260.     if (sockPtr->protoIndex != TCP_PROTO_INDEX) {
  1261.     panic("TCPSockToTCB: bad socket ptr\n");
  1262.     }
  1263.     return((TCPControlBlock *) sockPtr->protoData);
  1264. }
  1265.  
  1266. /*
  1267.  *----------------------------------------------------------------------
  1268.  *
  1269.  * TCPMakeTemplateHdr --
  1270.  *
  1271.  *    Create template to be used to send tcp packets on a connection.
  1272.  *    Call after host entry created, allocates an mbuf and fills
  1273.  *    in a skeletal tcp/ip header, minimizing the amount of work
  1274.  *    necessary when the connection is used.
  1275.  *
  1276.  * Results:
  1277.  *    None.
  1278.  *
  1279.  * Side effects:
  1280.  *    Memory for the headers is allocated.
  1281.  *
  1282.  *----------------------------------------------------------------------
  1283.  */
  1284.  
  1285. void
  1286. TCPMakeTemplateHdr(sockPtr, tcbPtr)
  1287.     Sock_SharedInfo     *sockPtr;
  1288.     TCPControlBlock    *tcbPtr;
  1289. {
  1290.     register Net_TCPHeader *tcpHdrPtr;
  1291.     register Net_IPHeader *ipHdrPtr;
  1292.  
  1293.     ipHdrPtr = (Net_IPHeader *) malloc(sizeof(Net_IPHeader));
  1294.     ipHdrPtr->protocol    = NET_IP_PROTOCOL_TCP;
  1295.     ipHdrPtr->source    = sockPtr->local.address;
  1296.     ipHdrPtr->dest    = sockPtr->remote.address;
  1297.     tcbPtr->IPTemplatePtr = ipHdrPtr;
  1298.  
  1299.     tcpHdrPtr = (Net_TCPHeader *) malloc(sizeof(Net_TCPHeader));
  1300.     tcpHdrPtr->srcPort    = sockPtr->local.port;
  1301.     tcpHdrPtr->destPort    = sockPtr->remote.port;
  1302.     tcpHdrPtr->seqNum    = 0;
  1303.     tcpHdrPtr->ackNum    = 0;
  1304.     tcpHdrPtr->dataOffset = sizeof(Net_TCPHeader) / 4;
  1305.     tcpHdrPtr->flags    = 0;
  1306.     tcpHdrPtr->window    = 0;
  1307.     tcpHdrPtr->checksum    = 0;
  1308.     tcpHdrPtr->urgentOffset= 0;
  1309.     tcbPtr->templatePtr = tcpHdrPtr;
  1310. }
  1311.  
  1312. /*
  1313.  *----------------------------------------------------------------------
  1314.  *
  1315.  * TCPDropConnection --
  1316.  *
  1317.  *    Drop a TCP connection, reporting the specified error to the user.
  1318.  *    If the connection is synchronized, then send a RESET to the remote
  1319.  *    peer.
  1320.  *
  1321.  * Results:
  1322.  *    None.
  1323.  *
  1324.  * Side effects:
  1325.  *    The TCB is destroyed.
  1326.  *
  1327.  *----------------------------------------------------------------------
  1328.  */
  1329.  
  1330. void
  1331. TCPDropConnection(sockPtr, tcbPtr, status)
  1332.     Sock_SharedInfo        *sockPtr;
  1333.     register TCPControlBlock    *tcbPtr;    /* TCB to be dropped. */
  1334.     ReturnStatus        status;        /* Error to give
  1335.                            to client. */
  1336. {
  1337.     if (tcbPtr == (TCPControlBlock *) NULL) {
  1338.     (void) fprintf(stderr, "TCPDropConnection: tcb == NULL\n");
  1339.     return;
  1340.     }
  1341.     if (TCP_HAVE_RECVD_SYN(tcbPtr->state)) {
  1342.     tcbPtr->state = CLOSED;
  1343.     (void) TCPOutput(sockPtr, tcbPtr);
  1344.     stats.tcp.drops++;
  1345.     } else {
  1346.     stats.tcp.connDrops++;
  1347.     }
  1348.     Sock_SetError(sockPtr, status);
  1349.     TCPCloseConnection(sockPtr, tcbPtr);
  1350. }
  1351.  
  1352. /*
  1353.  *----------------------------------------------------------------------
  1354.  *
  1355.  * TCPCloseConnection --
  1356.  *
  1357.  *    Close a TCP control block by  discarding all space held by the tcb,
  1358.  *    and waking any waiters.
  1359.  *
  1360.  * Results:
  1361.  *    None.
  1362.  *
  1363.  * Side effects:
  1364.  *    The TCB and socket may be destroyed.
  1365.  *
  1366.  *----------------------------------------------------------------------
  1367.  */
  1368.  
  1369. void
  1370. TCPCloseConnection(sockPtr, tcbPtr)
  1371.     Sock_SharedInfo        *sockPtr;
  1372.     register TCPControlBlock     *tcbPtr;
  1373. {
  1374.     if (!Sock_HasUsers(sockPtr)) {
  1375.     Sock_Destroy(sockPtr);
  1376.     } else {
  1377.     TCP_SocketDestroy((ClientData) tcbPtr);
  1378.     sockPtr->protoData = (ClientData) NULL;
  1379.     Sock_Disconnected(sockPtr);
  1380.     sockPtr->local.address = 0;
  1381.     sockPtr->local.port = 0;
  1382.     sockPtr->remote.address = 0;
  1383.     sockPtr->remote.port = 0;
  1384.     }
  1385.     stats.tcp.closed++;
  1386. }
  1387.  
  1388. /*
  1389.  *----------------------------------------------------------------------
  1390.  *
  1391.  * TCP_Quench --
  1392.  *
  1393.  *    When a source quench is received, close congestion window
  1394.  *    to one segment.  We will gradually open it again as we proceed.
  1395.  *
  1396.  * Results:
  1397.  *    None.
  1398.  *
  1399.  * Side effects:
  1400.  *    None.
  1401.  *
  1402.  *----------------------------------------------------------------------
  1403.  */
  1404.  
  1405. TCP_Quench(tcbPtr)
  1406.     TCPControlBlock *tcbPtr;
  1407. {
  1408.     if (tcbPtr != NULL) {
  1409.     tcbPtr->send.congWindow = tcbPtr->maxSegSize;
  1410.     }
  1411. }
  1412.  
  1413.  
  1414. /*
  1415.  *----------------------------------------------------------------------
  1416.  *
  1417.  * ConnQueueFull --
  1418.  *
  1419.  *    Checks if the connection queue of a listening socket is full.
  1420.  *
  1421.  * Results:
  1422.  *    TRUE    - the queue is full.
  1423.  *    FALSE    - the queue is not full.
  1424.  *
  1425.  * Side effects:
  1426.  *    None.
  1427.  *
  1428.  *----------------------------------------------------------------------
  1429.  */
  1430.  
  1431. static Boolean
  1432. ConnQueueFull(sockPtr)
  1433.     Sock_InfoPtr    sockPtr;    /* Listening socket. */
  1434. {
  1435.     register TCPConnectInfo *connPtr;
  1436.     connPtr = ((TCPControlBlock *)sockPtr->protoData)->connectPtr;
  1437.  
  1438.     if (((connPtr->tail+1) % connPtr->maxQueueSize) == connPtr->head) {
  1439.     return(TRUE);
  1440.     } 
  1441.     return(FALSE);
  1442. }
  1443.  
  1444.  
  1445. /*
  1446.  *----------------------------------------------------------------------
  1447.  *
  1448.  * ConnQueueNotEmpty --
  1449.  *
  1450.  *    Sees if the connection queue of a listening socket is not empty.
  1451.  *    If the mustBeConnected argument is TRUE, then if the queue
  1452.  *    is not empty, make sure the first socket in the queue is
  1453.  *    connected.
  1454.  *
  1455.  * Results:
  1456.  *    TRUE    - the queue is not empty.
  1457.  *    FALSE    - the queue is empty.
  1458.  *
  1459.  * Side effects:
  1460.  *    None.
  1461.  *
  1462.  *----------------------------------------------------------------------
  1463.  */
  1464.  
  1465. static Boolean
  1466. ConnQueueNotEmpty(sockPtr, mustBeConnected)
  1467.     Sock_InfoPtr    sockPtr;     /* Listening socket. */
  1468.     Boolean        mustBeConnected; /* If TRUE, make sure the first socket
  1469.                   * on the connection queue is connected. */
  1470. {
  1471.     register TCPConnectInfo *connPtr;
  1472.     connPtr = ((TCPControlBlock *)sockPtr->protoData)->connectPtr;
  1473.  
  1474.     if (connPtr->tail != connPtr->head) {
  1475.     if (!mustBeConnected) {
  1476.         return(TRUE);
  1477.     }
  1478.     /*
  1479.      * If the socket is still connecting, don't return TRUE yet.
  1480.      */
  1481.     if (connPtr->queue[connPtr->head]->state == CONNECTED) {
  1482.         return(TRUE);
  1483.     }
  1484.     } 
  1485.     return(FALSE);
  1486. }
  1487.  
  1488.  
  1489. /*
  1490.  *----------------------------------------------------------------------
  1491.  *
  1492.  * ConnQueueAppend --
  1493.  *
  1494.  *    Appends a sockPtr to a connection queue of listening socket.
  1495.  *
  1496.  * Results:
  1497.  *    None.
  1498.  *
  1499.  * Side effects:
  1500.  *    The queue is lengthened by 1.
  1501.  *
  1502.  *----------------------------------------------------------------------
  1503.  */
  1504.  
  1505. static void
  1506. ConnQueueAppend(sockPtr, newSockPtr)
  1507.     Sock_InfoPtr    sockPtr;        /* Listening socket. */
  1508.     Sock_InfoPtr    newSockPtr;    /* Socket for the new connection. */
  1509. {
  1510.     register TCPConnectInfo *connPtr;
  1511.     connPtr = ((TCPControlBlock *)sockPtr->protoData)->connectPtr;
  1512.     
  1513.     connPtr->queue[connPtr->tail] = newSockPtr;
  1514.     connPtr->tail = (connPtr->tail+1) % connPtr->maxQueueSize;
  1515. }
  1516.  
  1517.  
  1518. /*
  1519.  *----------------------------------------------------------------------
  1520.  *
  1521.  * ConnQueueNext --
  1522.  *
  1523.  *    Gets the next sockPtr on the connection queue of listening socket.
  1524.  *
  1525.  * Results:
  1526.  *    A Sock_SharedInfo ptr.
  1527.  *
  1528.  * Side effects:
  1529.  *    The queue is shortened by 1.
  1530.  *
  1531.  *----------------------------------------------------------------------
  1532.  */
  1533.  
  1534. static Sock_InfoPtr    
  1535. ConnQueueNext(sockPtr)
  1536.     Sock_InfoPtr    sockPtr;        /* Listening socket. */
  1537. {
  1538.     Sock_InfoPtr    newPtr;
  1539.     register TCPConnectInfo *connPtr;
  1540.  
  1541.     connPtr = ((TCPControlBlock *)sockPtr->protoData)->connectPtr;
  1542.     
  1543.     newPtr = connPtr->queue[connPtr->head];
  1544.     connPtr->head = (connPtr->head+1) % connPtr->maxQueueSize;
  1545.     return(newPtr);
  1546. }
  1547. @
  1548.  
  1549.  
  1550. 1.11
  1551. log
  1552. @Wasn't starting output during write if buffer filled!  Thus if
  1553. a single write operation completely filled the buffer the
  1554. connection hung.
  1555. @
  1556. text
  1557. @d28 1
  1558. a28 1
  1559. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpSock.c,v 1.10 89/05/19 15:24:24 douglis Exp $ SPRITE (Berkeley)";
  1560. a966 1
  1561.     tcbPtr = (TCPControlBlock *) sockPtr->protoData;
  1562. d969 3
  1563. a971 1
  1564.      * We expect at least 4 bytes of data.
  1565. d973 2
  1566. a974 1
  1567.     if (inBufSize < sizeof(int)) {
  1568. d977 2
  1569. @
  1570.  
  1571.  
  1572. 1.10
  1573. log
  1574. @added debugging msgs when tcp bind fails.
  1575. @
  1576. text
  1577. @d28 1
  1578. a28 1
  1579. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpSock.c,v 1.9 89/03/23 10:55:46 brent Exp Locker: douglis $ SPRITE (Berkeley)";
  1580. d385 2
  1581. d392 1
  1582. a392 1
  1583.     if (status == SUCCESS) {
  1584. @
  1585.  
  1586.  
  1587. 1.9
  1588. log
  1589. @Nuked the tcb == NULL print message from TCP_Close becuase
  1590. this is a normal case that happens when a connection
  1591. is reset before it gets established.
  1592. @
  1593. text
  1594. @d28 1
  1595. a28 1
  1596. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpSock.c,v 1.8 89/03/23 09:54:04 brent Exp $ SPRITE (Berkeley)";
  1597. d504 3
  1598. d524 5
  1599. d552 3
  1600. @
  1601.  
  1602.  
  1603. 1.8
  1604. log
  1605. @Removed stdio.h include
  1606. @
  1607. text
  1608. @d28 1
  1609. a28 1
  1610. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpSock.c,v 1.7 89/02/21 10:10:54 brent Exp $ SPRITE (Berkeley)";
  1611. d144 2
  1612. a145 1
  1613.      * The TCB should be NULL if shutdown was called on the socket.
  1614. a147 1
  1615.     (void) fprintf(stderr, "TCP Close: tcb == NULL\n");
  1616. @
  1617.  
  1618.  
  1619. 1.7
  1620. log
  1621. @Added constants for the SEND and RECV buffer sizes
  1622. @
  1623. text
  1624. @d28 1
  1625. a28 1
  1626. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpSock.c,v 1.6 88/12/14 09:21:33 douglis Exp Locker: brent $ SPRITE (Berkeley)";
  1627. a41 2
  1628.  
  1629. #include <stdio.h>
  1630. @
  1631.  
  1632.  
  1633. 1.6
  1634. log
  1635. @?? This is ouster checking in for douglis.
  1636. @
  1637. text
  1638. @d28 1
  1639. a28 1
  1640. static char rcsid[] = "$Header: /a/daemons/ipServer/RCS/tcpSock.c,v 1.5 88/10/24 13:09:57 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1641. d48 2
  1642. a49 2
  1643. #define SEND_SPACE    4096
  1644. #define RECV_SPACE    4096
  1645. @
  1646.  
  1647.  
  1648. 1.5
  1649. log
  1650. @Added check for NULL ptr when destroying socket.
  1651. @
  1652. text
  1653. @d28 1
  1654. a28 1
  1655. static char rcsid[] = "$Header: /a/daemons/ipServer/RCS/tcpSock.c,v 1.4 88/10/17 10:20:10 ouster Exp Locker: douglis $ SPRITE (Berkeley)";
  1656. d835 1
  1657. a835 1
  1658.     return(SUCCESS);
  1659. d1240 2
  1660. a1241 1
  1661.     ReturnStatus        status;        /* Error to give to client. */
  1662. d1243 4
  1663. @
  1664.  
  1665.  
  1666. 1.4
  1667. log
  1668. @Added code for dynamic routing table  updates.
  1669. @
  1670. text
  1671. @d28 1
  1672. a28 1
  1673. static char rcsid[] = "$Header: tcpSock.c,v 1.3 88/08/16 11:19:27 mendel Exp $ SPRITE (Berkeley)";
  1674. d827 10
  1675. @
  1676.  
  1677.  
  1678. 1.3
  1679. log
  1680. @Converted to use new libc.a
  1681. @
  1682. text
  1683. @d28 1
  1684. a28 1
  1685. static char rcsid[] = "$Header: tcpSock.c,v 1.2 88/04/27 09:10:30 brent Exp $ SPRITE (Berkeley)";
  1686. d503 2
  1687. a504 1
  1688.     if (temp.address != NET_INET_ANY_ADDR) {
  1689. d521 1
  1690. a521 1
  1691.     if ((temp.port < INET_PRIV_PORTS) && 
  1692. d544 2
  1693. a545 1
  1694.             NET_INET_ANY_ADDR, 0, wildcard) != (Sock_InfoPtr    ) NULL) {
  1695. a591 1
  1696.  
  1697. d614 1
  1698. a614 1
  1699.     if (remote.address == NET_INET_ANY_ADDR) {
  1700. d616 1
  1701. a616 1
  1702.     } else if (remote.address == NET_INET_BROADCAST_ADDR) {
  1703. d620 1
  1704. a620 1
  1705.     if (sockPtr->local.address == NET_INET_ANY_ADDR) {
  1706. d730 1
  1707. a730 1
  1708.     sockAddr.address = NET_INET_ANY_ADDR;
  1709. d1048 2
  1710. d1056 4
  1711. a1059 3
  1712.     } while (Sock_Match(TCP_PROTO_INDEX, localAddr, port, 
  1713.             NET_INET_ANY_ADDR, 0, FALSE) != (Sock_InfoPtr    ) NULL);
  1714.     return(port);
  1715. @
  1716.  
  1717.  
  1718. 1.2
  1719. log
  1720. @New update with Jacobson enhancements
  1721. @
  1722. text
  1723. @d28 1
  1724. a28 1
  1725. static char rcsid[] = "$Header: tcpSock.c,v 6.2 88/04/24 23:13:42 andrew Exp $ SPRITE (Berkeley)";
  1726. d43 1
  1727. a43 6
  1728. #include "fs.h"
  1729. #include "io.h"
  1730. #include "mem.h"
  1731. #include "sys.h"
  1732. #include "byte.h"
  1733. #include "sig.h"
  1734. a44 1
  1735.  
  1736. d87 1
  1737. a87 1
  1738.     tcbPtr = Mem_New(TCPControlBlock);
  1739. d90 1
  1740. a90 1
  1741.     Byte_Zero(sizeof(*tcbPtr), (Address) tcbPtr);
  1742. d149 1
  1743. a149 1
  1744.     Io_PrintStream(io_StdErr, "TCP Close: tcb == NULL\n");
  1745. d161 1
  1746. a161 1
  1747.         Sock_SharedInfo *connPtr = ConnQueueNext(sockPtr);
  1748. d543 1
  1749. a543 1
  1750.             NET_INET_ANY_ADDR, 0, wildcard) != (Sock_SharedInfo *) NULL) {
  1751. d632 1
  1752. a632 1
  1753.         (Sock_SharedInfo *) NULL) {
  1754. d653 1
  1755. a653 1
  1756.         (Sock_SharedInfo *) NULL) {
  1757. d748 1
  1758. a748 1
  1759.     connectPtr = Mem_New(TCPConnectInfo);
  1760. d828 1
  1761. a828 1
  1762.     Mem_Free((Address) tcbPtr->connectPtr);
  1763. d831 1
  1764. a831 1
  1765.     Mem_Free((Address) tcbPtr->templatePtr);
  1766. d834 1
  1767. a834 1
  1768.     Mem_Free((Address) tcbPtr->IPTemplatePtr);
  1769. d839 1
  1770. a839 1
  1771.     Mem_Free((Address) tcbPtr);
  1772. d1054 1
  1773. a1054 1
  1774.             NET_INET_ANY_ADDR, 0, FALSE) != (Sock_SharedInfo *) NULL);
  1775. d1077 1
  1776. a1077 1
  1777. Sock_SharedInfo *
  1778. d1089 1
  1779. a1089 1
  1780.     Sys_Panic(SYS_FATAL, 
  1781. d1098 1
  1782. a1098 1
  1783.     return((Sock_SharedInfo *)NULL);
  1784. d1122 1
  1785. a1122 1
  1786.     return((Sock_SharedInfo *)NULL);
  1787. d1150 1
  1788. a1150 1
  1789.     Sock_SharedInfo *sockPtr;
  1790. d1153 1
  1791. a1153 1
  1792.     Sys_Panic(SYS_FATAL, "TCPSockToTCB: bad socket ptr\n");
  1793. d1185 1
  1794. a1185 1
  1795.     ipHdrPtr = Mem_New(Net_IPHeader);
  1796. d1191 1
  1797. a1191 1
  1798.     tcpHdrPtr = Mem_New(Net_TCPHeader);
  1799. d1320 1
  1800. a1320 1
  1801.     Sock_SharedInfo *sockPtr;    /* Listening socket. */
  1802. d1354 1
  1803. a1354 1
  1804.     Sock_SharedInfo *sockPtr;     /* Listening socket. */
  1805. d1394 2
  1806. a1395 2
  1807.     Sock_SharedInfo *sockPtr;        /* Listening socket. */
  1808.     Sock_SharedInfo *newSockPtr;    /* Socket for the new connection. */
  1809. d1421 1
  1810. a1421 1
  1811. static Sock_SharedInfo *
  1812. d1423 1
  1813. a1423 1
  1814.     Sock_SharedInfo *sockPtr;        /* Listening socket. */
  1815. d1425 1
  1816. a1425 1
  1817.     Sock_SharedInfo *newPtr;
  1818. @
  1819.  
  1820.  
  1821. 1.1
  1822. log
  1823. @Initial revision
  1824. @
  1825. text
  1826. @d9 2
  1827. a10 2
  1828.  *    "@@(#)tcp_subr.c      7.6 (Berkeley) 6/6/87"
  1829.  *    "@@(#)tcp_usrreq.c 7.5 (Berkeley) 5/8/87"
  1830. d28 1
  1831. a28 1
  1832. static char rcsid[] = "$Header: tcpSock.c,v 6.0 87/09/08 15:56:44 andrew Stable $ SPRITE (Berkeley)";
  1833. d100 10
  1834. a109 1
  1835.     tcbPtr->smoothRTT        = TCP_SRTT_BASE_TIME;
  1836. d111 1
  1837. d677 1
  1838. a677 1
  1839.     tcbPtr->timer[TCP_TIMER_KEEP_ALIVE] = TCP_KEEP_TIME;
  1840. d921 104
  1841. @
  1842.